package com.shiyanlou.upms.common.config;

import com.shiyanlou.upms.common.utils.ShiroUtils;
import com.shiyanlou.upms.system.domain.UpmsUser;
import com.shiyanlou.upms.system.service.UpmsPermissionService;
import com.shiyanlou.upms.system.service.UpmsUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UpmsPermissionService upmsPermissionService;

    @Autowired
    private UpmsUserService upmsUserService;

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */

    /*doGetAuthenticationInfo 是一个方法，通常在实现认证功能时被重写。它接受一个 AuthenticationToken 参数，并返回一个 AuthenticationInfo 对象。
AuthenticationToken 是用于封装用户提交的身份验证信息的对象，例如用户名和密码等。AuthenticationException 是认证过程中可能抛出的异常，用于表示认证失败的情况。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String userName = (String) authenticationToken.getPrincipal();
        String password = new String((char[]) authenticationToken.getCredentials());
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("username", userName);
        List<UpmsUser> userList = upmsUserService.list(paramMap);
        if(userList == null || userList.size() == 0) {
            throw new UnknownAccountException("用户名或密码错误！");
        }
        UpmsUser user = userList.get(0);
        if (user == null) {
            throw new UnknownAccountException("用户名或密码错误！");
        }
        if (!password.equals(user.getPassword())) {
            throw new UnknownAccountException("用户名或密码错误！");
        }
        if (user.getLocked() > 0) {
            throw new LockedAccountException("用户已锁定，请稍后再试！");
        }
        //SimpleAuthenticationInfo 是 AuthenticationInfo 接口的一个实现类。它是 Shiro 框架提供的一个简单的身份验证信息对象。
        /*
        构造 SimpleAuthenticationInfo 对象时，通常会传入三个参数：
        principal：表示用户的身份信息，例如用户名或用户对象。在 Shiro 中，主体（Subject）通常是指代用户。
        credentials：表示用户的凭证信息，例如密码。在 Shiro 中，凭证（Credentials）通常是指代用户的密码。
        realmName：表示用户所属的 Realm 名称，用于标识该身份验证信息是由哪个 Realm 提供的。
        */
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
        return info;
    }

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Integer userId = ShiroUtils.getUserId();
        Set<String> upmsPermissionDOSet = upmsPermissionService.selectByUserId(userId);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(upmsPermissionDOSet);
        return info;
    }
}